#include <stm32f10x.h>
#include <stdbool.h>
#include <stdio.h>
#include "printf.h"

typedef unsigned char byte;

void delay_ms(unsigned int ms)
{
    int n = 0;
    while (ms--)
    {
        for (n = 0; n < 1000; n++)
            ;
    }
}

void init_GPIOA_0_7()
{
    GPIO_InitTypeDef def;

    def.GPIO_Mode = GPIO_Mode_Out_PP;
    def.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    def.GPIO_Speed = GPIO_Speed_50MHz;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_Init(GPIOA, &def);

    def.GPIO_Mode = GPIO_Mode_IPU;
    def.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_Init(GPIOA, &def);
}

int read_key_no()
{

    int rd = -1;
    byte A7_0 = 0xEF;

    GPIO_Write(GPIOA, 0x0F);

    rd = GPIO_ReadInputData(GPIOA);
    printf("read_key_no %d %#X\r\n", __LINE__, rd);
    // 检测有按键按下
    if ((rd & 0xFF) != 0x0F)
    {
        delay_ms(10); // 消抖
        // 第二次读取，看是否还按下按键
        rd = GPIO_ReadInputData(GPIOA);
        if ((rd & 0xFF) != 0x0F)
        {
            // 计算是哪一个按键
            // 给字节高四位写入数据0xE 1110
            byte hb = 0xE;

            while (hb != 0xF) // 必须清零高四位否者，比较不成立时会无限循环
            {
                printf("read_key_no %d hb = %#X\r\n", __LINE__, hb);
                // 低四位必须写入1，否则，会写入多少，就会读取多少
                A7_0 = hb << 4 | 0xF;
                // 给字节高四位写入数据 也就是 A4~A7
                GPIO_Write(GPIOA, A7_0);
                // 读值，这里面有个东西就是GPIO输出的值可以读取！！！输出多少读取就是多少！！！
                rd = GPIO_ReadInputData(GPIOA);
                printf("read_key_no %d %#X\r\n", __LINE__, rd);
                switch (rd & 0xFF)
                {
                case 0xE7:
                    return 16;
                case 0xD7:
                    return 15;
                case 0xB7:
                    return 14;
                case 0x77:
                    return 13;

                case 0xEB:
                    return 12;
                case 0xDB:
                    return 11;
                case 0xBB:
                    return 10;
                case 0x7B:
                    return 9;

                case 0xED:
                    return 8;
                case 0xDD:
                    return 7;
                case 0xBD:
                    return 6;
                case 0x7D:
                    return 5;

                case 0xEE:
                    return 4;
                case 0xDE:
                    return 3;
                case 0xBE:
                    return 2;
                case 0x7E:
                    return 1;
                }
                hb <<= 1;
                hb |= 1;
                hb &= 0xF; // 清除hb的高四位为0
            }
        }
    }

    return -1;
}

int main()
{

    init_GPIOA_0_7();
    printf_init(9600);

    while (true)
    {
        // printf("%#X\r\n", GPIO_ReadInputData(GPIOA));
        printf("%d\r\n", read_key_no());
        delay_ms(5000);
    }

    return 0;
}
